package cn.melonlib.security.encryption.model;


import cn.hutool.core.util.ByteUtil;

import java.io.ByteArrayOutputStream;
import java.io.Serializable;
import java.util.UUID;

/**
 * 加密包
 * @author spini
 *
 */
@SuppressWarnings("serial")
public class EncPackage implements Serializable{
	
	private EncPackage(byte[]val, int length, long createTime, String uuid){
		this.length=length;
		this.createTime=createTime;
		this.val=val;
		this.uuid=uuid;
	}
	
	private final int length;
	
	private final long createTime;
	
	private final byte[] val;
	
	private final String uuid;
	
	/**
	 * 根据给定数据创建一个加密数据包
	 * @param val 给定数据
	 * @return 加密包
	 */
	public static EncPackage createEncPackage(byte[]val){
		return new EncPackage(val, val.length,System.currentTimeMillis(),UUID.randomUUID().toString().replace("-",""));
	}
	
	/**
	 * 解析一个已序列化的加密包
	 * @param data 加密包数据
	 * @return 加密包
	 * @throws Exception
	 */
	public static EncPackage parseData(byte[]data) throws Exception{
		ByteArrayOutputStream out=new ByteArrayOutputStream();
		out.write(data,0,8);
		long createTime= ByteUtil.bytesToLong(out.toByteArray()) ;
		out.reset();
		out.write(data, 8, 4);
		int length= ByteUtil.bytesToInt(out.toByteArray());
		
		out.reset();
		out.write(data, 12+length, 32);
		byte [] ubs=out.toByteArray();
		String uuid=new String(ubs,"utf-8");

		out.reset();
		for (int i = 12; i < 12+length; i++) {
			out.write(data[i]^ubs[(i-12)%32]);
		}
		byte[]val =out.toByteArray();
		return new EncPackage(val, length, createTime, uuid);
	}
	
	/**
	 * 将加密包序列化
	 * @return
	 * @throws Exception
	 */
	public byte[] toData()throws Exception{
		ByteArrayOutputStream out=new ByteArrayOutputStream();
		out.write(ByteUtil.longToBytes(createTime));
		out.write(ByteUtil.intToBytes(length));
		byte[] ubs=uuid.getBytes("utf-8");
		for (int i = 0; i < val.length; i++) {
			out.write(val[i]^ubs[i%32]);
		}
		out.write(ubs);
		return out.toByteArray();
	}

	/**
	 * 获取数据长度
	 * @return
	 */
	public int getLength() {
		return length;
	}

	/**
	 * 加密包创建时间
	 * @return
	 */
	public long getCreateTime() {
		return createTime;
	}

	/**
	 * 数据实体
	 * @return
	 */
	public byte[] getVal() {
		return val;
	}

	/**
	 * 随机UUID
	 * @return
	 */
	public String getUuid() {
		return uuid;
	}
}
